#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include"Protocol.hpp"

#define NUM 1024

class Calclient
{
public:
    Calclient(const std::string serverip, const uint16_t serverport) : _serverip(serverip), _serverport(serverport), _sock(-1)
    {
    }
    void initClient()
    {
        _sock = socket(AF_INET, SOCK_STREAM, 0);
        if (_sock < 0)
        {
            std::cerr << "socket create error" << std::endl;
            exit(2);
        }

    }
    void start()
    {  struct sockaddr_in server;
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_port = htons(_serverport);
        server.sin_addr.s_addr = inet_addr(_serverip.c_str());
        if(connect(_sock,(struct sockaddr*)&server,sizeof(server))!=0)
        {
            std::cerr << "socket connect error" << std::endl;
        }
        else
        { std::string s;
          std::string inbuffer;
            while(true)
            {  //1.发信息
                std::cout<<"enter";
                std::getline(std::cin,s);
                Request req=parseLine(s);
                std::string content;
               req.serialize(&content);
              string send_content= enlength(content);              
                send(_sock,send_content.c_str(),send_content.size(),0);
                std::cout << "sendstring:\n" << send_content<< std::endl;
                //2.收信
                std::string text,package;
                if(!recvpackage(_sock,inbuffer,&package)) continue;
             
                if(!delength(package,&text)) continue;
                Response resp;
                resp.deserialize(text);
                std::cout << "exitCode: " << resp.exitcode<< std::endl;
                std::cout << "result: " << resp.result << std::endl;
               
            }
            
        }
         
    }
       
    Request parseLine(const std::string &line)//将io转换为结构体
    {  int status=0;//字符的状态：0左边字符型数字，1运算符，2右边字符型数字
       int i=0;//字符下标
       int cnt =line.size();
       std::string left,right;//获取符号两边的字符型数字
       char op;//中间运算符
       while(i<cnt)
       { switch(status)
            {case 0:
             {if(!isdigit(line[i]))//判断是否为字符型数字
             {  status=1;
                op=line[i];
             }
             else left.push_back(line[i++]);
             break;
            }
             case 1:
              {
              i++;
              status=2;
              break;
              }
              case 2:
              { right.push_back(line[i++]);
                 break;
              }
            }
       }
     std::cout << std::stoi(left)<<" " << std::stoi(right) << " " << op << std::endl;
        return Request(std::stoi(left), std::stoi(right), op);
       


    }
    ~Calclient()
    {
        if(_sock >= 0) close(_sock);
    }

private:
    uint16_t _serverport;
    std::string _serverip;
    int _sock;
};